/////////////////////////////////////////////     File     //////////////////////////////////////////////////
// Author: James Chen
// Filename: CUtilities.h
// Created: Friday, January 29, 2010 12:10:03 PM
/////////////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once

#include <windows.h> /* required for srand() */
#include <ctime>
#include <pdh.h>
#include <vector>

using namespace std;

#include <d3d10.h>
#include <d3dx10.h>
#include <dxerr.h>
#include <cassert>
#include <fstream>

#pragma comment(lib, "d3d10.lib")
#pragma comment(lib, "d3dx10.lib")

#pragma comment(lib, "pdh.lib")

#include "Globals.h"

/*---------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------*/

// Enable extra D3D debugging in debug builds if using the debug DirectX runtime.  
// This makes D3D objects work well in the debugger watch window, but slows down 
// performance slightly.
#if defined(DEBUG) || defined(_DEBUG)
	#ifndef D3D_DEBUG_INFO
	#define D3D_DEBUG_INFO
	#endif
#endif

#if defined(DEBUG) || defined(_DEBUG)
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#endif

#if defined(DEBUG) | defined(_DEBUG)
	#ifndef HR
	#define HR(x)                                              \
	{                                                          \
		HRESULT hr = (x);                                      \
		if(FAILED(hr))                                         \
		{                                                      \
			DXTrace(__FILE__, (DWORD)__LINE__, hr, L#x, true); \
		}                                                      \
	}
	#endif

#else
	#ifndef HR
	#define HR(x) (x)
	#endif
#endif 

/*---------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------*/

enum RNDTYPE {FASTMW, FASTW, FASTI, FASTSEED, SLOW, SIZEOF};

enum PATHTYPE {LINEAR, SLERP, BEZIER};

const D3DXCOLOR WHITE(1.0f, 1.0f, 1.0f, 1.0f);
const D3DXCOLOR BLACK(0.0f, 0.0f, 0.0f, 1.0f);
const D3DXCOLOR RED(1.0f, 0.0f, 0.0f, 1.0f);
const D3DXCOLOR GREEN(0.0f, 1.0f, 0.0f, 1.0f);
const D3DXCOLOR BLUE(0.0f, 0.0f, 1.0f, 1.0f);
const D3DXCOLOR YELLOW(1.0f, 1.0f, 0.0f, 1.0f);
const D3DXCOLOR CYAN(0.0f, 1.0f, 1.0f, 1.0f);
const D3DXCOLOR MAGENTA(1.0f, 0.0f, 1.0f, 1.0f);

const D3DXCOLOR BEACH_SAND(1.0f, 0.96f, 0.62f, 1.0f);
const D3DXCOLOR LIGHT_YELLOW_GREEN(0.48f, 0.77f, 0.46f, 1.0f);
const D3DXCOLOR DARK_YELLOW_GREEN(0.1f, 0.48f, 0.19f, 1.0f);
const D3DXCOLOR DARKBROWN(0.45f, 0.39f, 0.34f, 1.0f);

#define POLLRATE 1
#define TIMERPOLLRATE 0.5

/*---------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------*/

#if 0 //Included Classes

	RNGen				// Random Number Generator *Singleton*
	CTimer				// Precision Timer
	CMath				// Math functions *Singleton*
	CSystemAnalysis		// Performance monintoring *Singleton*
	CPathing			// 3D Pathing with no A* or Collision (may include both at a later time)
	CConversion			// Conversion Class *Singleton*

#endif

/*---------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------*/

template <typename TYPE>
void Swap(TYPE& x, TYPE& y)
{
	x ^= y;
	y ^= x;
	x ^= y;
}

/*---------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------*/

/////////////////////////////////////////////     Class     /////////////////////////////////////////////////
// Name: RNGen
// Author: James Chen
// Created: Friday, January 29, 2010 12:10:04 PM
//
// Purpose: Random Number Generator
//
// Revisions: 
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
class RNGen
{
	////////////////////// Singleton Implementation Begins //////////////////////
private:

	RNGen(void);
	RNGen(const RNGen&);
	RNGen& operator =(const RNGen&);
	static RNGen *m_pInstance;
	
	double ReturnValue;
	double Ratio;

	float ReturnValueF;
	unsigned int RN;
	unsigned int SEED;

	int MZ;
	int MW;

public:

	virtual ~RNGen(void);
	static RNGen *GetInstance(void);
	static void DeleteInstance(void);
	/////////////////////// Singleton Implementation Ends ///////////////////////

	unsigned int GetLastRN(void)
	{
		return this->RN;
	}

	void Reseed(void);

	bool LoadLastSeed(void);			/* Loads the last saved seed for FASTSEED from text file [8/12/2010 10:43 AM by: James Chen] */
	bool SaveSeed(void);				/* Saves the seed for FASTSEED for future use for debugging purposes or saved game usage [8/12/2010 10:43 AM by: James Chen] */

	//Fast RNGs generate the same numbers every run
	unsigned int FastMW(void);
	unsigned int FastW(void);
	unsigned int FastI(void);

	unsigned int FastSeed(void); // This is a fast implementation that uses random seeds to seed a fast implementation for true random numbers every program call thus unpredictable unless you have the seed values of the program call

	//Slow RNGs are harder to predict
	unsigned int Slow(void);

	double RandD(RNDTYPE TYPE, double LowValue, double HighValue);
	float RandF(RNDTYPE TYPE, float LowValue, float HighValue);

	D3DX10INLINE D3DXVECTOR3 RandUnitVec3F(RNDTYPE TYPE)
	{
		D3DXVECTOR3 value;

		switch(TYPE)
		{
		case FASTMW:
			{
				value.x = RandF(FASTMW, 0.0f, 1.0f);
				value.y = RandF(FASTMW, 0.0f, 1.0f);
				value.z = RandF(FASTMW, 0.0f, 1.0f);
			}
		case FASTW:
			{
				value.x = RandF(FASTW, 0.0f, 1.0f);
				value.y = RandF(FASTW, 0.0f, 1.0f);
				value.z = RandF(FASTW, 0.0f, 1.0f);
			}
		case FASTI:
			{
				value.x = RandF(FASTI, 0.0f, 1.0f);
				value.y = RandF(FASTI, 0.0f, 1.0f);
				value.z = RandF(FASTI, 0.0f, 1.0f);
			}
		case FASTSEED:
			{
				value.x = RandF(FASTSEED, 0.0f, 1.0f);
				value.y = RandF(FASTSEED, 0.0f, 1.0f);
				value.z = RandF(FASTSEED, 0.0f, 1.0f);
			}
		case SLOW:
			{
				value.x = RandF(SLOW, 0.0f, 1.0f);
				value.y = RandF(SLOW, 0.0f, 1.0f);
				value.z = RandF(SLOW, 0.0f, 1.0f);
			}
		default:
			{

			}
		};

		D3DXVec3Normalize(&value, &value);

		return value;
	}

	//////////////////////////////////////////     Accessors     ////////////////////////////////////////////////
	// Author: James Chen
	// Created: Tuesday, February 02, 2010 9:30:20 AM
	//
	// Purpose: returns the specified type
	//
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////
	inline int& GetSeedValue1(void)
	{
		return MZ;
	}

	inline int& GetSeedValue2(void)
	{
		return MW;
	}

	///////////////////////////////////////////     Mutators     ////////////////////////////////////////////////
	// Author: James Chen
	// Created: Tuesday, February 02, 2010 9:30:29 AM
	//
	// Purpose: sets the class' variables
	//
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////
	inline void SetSeedValue1(int mz)
	{
		this->MZ = mz;
	}

	inline void SetSeedValue2(int mw)
	{
		this->MW = mw;
	}
};

/*---------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------*/


/////////////////////////////////////////////     Class     /////////////////////////////////////////////////
// Name: CTimer
// Author: James Chen
// Created: Thursday, January 29, 2010 12:10:04 PM
//
// Purpose: Timer class that keeps track of the current time
//
// Revisions: 
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CTimer
{
private:

	vector<double> m_vProfiler;				
	vector<double>::iterator ITERATOR;

	LARGE_INTEGER m_liTickFrequency;		/* The tick frequency */
	double m_dTimeStart;					/* The start time */
	double m_dTimeDelta;					/* The change in time since the last update */
	double m_dAccumulation;					/* Quantifies Work Time [8/13/2010 9:40 AM by: James Chen] */
	double m_dRunTime;						/* The run time of the timer without including the paused time [8/13/2010 9:41 AM by: James Chen] */
	int m_nFPS;								/* Updates per second */
	bool m_bPaused;							/* This allows the timer to be paused [5/9/2010 11:42 PM by: James Chen] */

public:

	CTimer(void);
	virtual ~CTimer(void);

	void Initialize(void);
	void Update(void);
	double GetTimeSinceStart(void);				/* This function will include Paused time. [5/10/2010 12:42 AM by: James Chen] */
	double GetAverageWorkTime(void);			/* This function will calculate the average time it takes to complete a certain section of code [8/12/2010 9:48 AM by: James Chen] */
	bool GetAverageWorkTimeByCount(unsigned int Count, double &average); /* This function will produce the average work time of code after the counter has been reached [8/12/2010 9:49 AM by: James Chen] */

	inline double GetDeltaTime(void)
	{
		return this->m_dTimeDelta < 0.0 ? 0.0 : this->m_dTimeDelta;  /* If the application gets bumped to another processor delta time can be negative [8/13/2010 9:38 AM by: James Chen] */
	}

	inline double GetRunTime(void)
	{
		return this->m_dRunTime;
	}

	inline int GetFPS(void)
	{
		return this->m_nFPS;
	}

	inline void Pause(void)
	{
		this->m_bPaused = true;
	}

	inline void Unpause(void)
	{
		this->m_bPaused = false;
	}

	inline void AddWorkTime(double time)
	{
		this->m_vProfiler.push_back(time);
	}
};

/*---------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------*/


/////////////////////////////////////////////     Class     /////////////////////////////////////////////////
// Name: CMath
// Author: James Chen
// Created: Wednesday, February 03, 2010 3:07:43 PM
//
// Purpose: Math helper functions
//
// Revisions: 
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CMath
{
	////////////////////// Singleton Implementation Begins //////////////////////
private:

	CMath(void);
	CMath(const CMath&);
	CMath& operator =(const CMath&);
	static CMath *m_pInstance;

	float m_fTheta;

public:

	virtual ~CMath(void);
	static CMath *GetInstance(void);
	static void DeleteInstance(void);
	/////////////////////// Singleton Implementation Ends ///////////////////////

	float LinearInterpolationF(const float &Min, const float &Max, const float &Progression);
	double LinearInterpolationD(const double &Min, const double &Max, const double &Progression);

	D3DXVECTOR3 Slerp3D(const D3DXVECTOR3 &start, const D3DXVECTOR3 &end, const float &Progression);
	D3DXVECTOR2 Slerp2D(const D3DXVECTOR2 &start, const D3DXVECTOR2 &end, const float &Progression);

	double DistanceFast(const D3DXVECTOR3 &start, const D3DXVECTOR3 &end);
	double DistanceTrue(const D3DXVECTOR3 &start, const D3DXVECTOR3 &end);
	double DistanceFast(const double &xDiff, const double &yDiff, const double &zDiff);
	double DistanceTrue(const double &xDiff, const double &yDiff, const double &zDiff);
};

/*---------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------*/


/////////////////////////////////////////////     Class     /////////////////////////////////////////////////
// Name: CSystemAnalysis
// Author: James Chen
// Created: Saturday, April 24, 2010 10:45:35 PM
//
// Purpose: Performs anaylysis on the system
//
// Revisions: 
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CSystemAnalysis
{
	////////////////////// Singleton Implementation Begins //////////////////////
private:

	CSystemAnalysis(void);
	CSystemAnalysis(const CSystemAnalysis&);
	CSystemAnalysis& operator =(const CSystemAnalysis&);
	static CSystemAnalysis *m_pInstance;

	//CPU Polling
	bool m_canReadCpu;
	HQUERY m_queryHandle;
	HCOUNTER m_counterHandle;
	unsigned long m_ulLastSampleTime;
	PDH_FMT_COUNTERVALUE m_value;
	long m_cpuUsage;

	//Memory Polling
	MEMORYSTATUSEX memstat;

public:

	virtual ~CSystemAnalysis(void);
	static CSystemAnalysis *GetInstance(void);
	static void DeleteInstance(void);
	/////////////////////// Singleton Implementation Ends ///////////////////////

	void Initialize(void);
	void Shutdown(void);
	void Update(void);
	int GetCpuUsage(void);
	double GetMemUsage(void);


};

/*---------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------*/


/////////////////////////////////////////////     Class     /////////////////////////////////////////////////
// Name: CPath
// Author: James Chen
// Created: Monday, May 10, 2010 5:24:52 PM
//
// Purpose: Pathing with set waypoints
//
// Revisions: 
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CPathing
{
private:
	vector<D3DXVECTOR3> m_vPath;

	vector<D3DXVECTOR3>::iterator m_Iterator;
	vector<D3DXVECTOR3>::iterator m_PositionIterator;

	D3DXVECTOR3 *m_pVecPosition;
	D3DXVECTOR3 m_VecPosition;

	PATHTYPE m_nPathType;
	double m_dSpeed;
	double m_dRemainingSpeed;
	double m_dTravelDistance;
	double m_dTotalDistance;
	bool m_bContinuous;
	bool m_bLinked;

public:
	CPathing(void);
	virtual ~CPathing(void);


	void RemoveWaypoint(const int &ArrayPosition);
	void Update(const float &DeltaTime);
	void AddWaypoints(const D3DXVECTOR3 *Waypoints, const int Count);
	void RotateYAxis(const float &angle);
	double CalculateDistance(void);
	void Reset(void);


	void AddWaypoint(const D3DXVECTOR3 &Waypoint)
	{
		this->m_vPath.push_back(Waypoint);

		if(this->m_vPath.size() == 1)
		{
			this->m_PositionIterator = this->m_vPath.begin();
		}
	}

	void KillPath(void)
	{
		this->m_vPath.clear();
	}

	void LinkToPath(D3DXVECTOR3 *positionVector = 0)
	{
		if(positionVector)
		{
			this->m_bLinked = true;

			this->m_pVecPosition = positionVector;

			return;
		}
	}

	void UnlinkToPath()
	{
		this->m_bLinked = false;

		this->m_pVecPosition = 0;
	}

	///////////////////////////////////////////     Mutators     ////////////////////////////////////////////////
	// Author: James Chen
	// Created: Monday, May 10, 2010 6:59:56 PM
	//
	// Purpose: sets the class' variables
	//
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////

	void SetType(PATHTYPE TYPE)
	{
		this->m_nPathType = TYPE;
	}

	void SetSpeed(const double &Speed)
	{
		this->m_dSpeed = Speed;
	}

	void SetContinuous(const bool &Continuous)
	{
		this->m_bContinuous = Continuous;
	}

	//////////////////////////////////////////     Accessors     ////////////////////////////////////////////////
	// Author: James Chen
	// Created: Monday, May 10, 2010 6:59:47 PM
	//
	// Purpose: returns the specified type
	//
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////

	PATHTYPE GetType(void)
	{
		return this->m_nPathType;
	}

	double GetTotalDistance(void)
	{
		return this->m_dTotalDistance;
	}

	D3DXVECTOR3 GetPosition(void)
	{
		return this->m_VecPosition;
	}
};


/////////////////////////////////////////////     Class     /////////////////////////////////////////////////
// Name: CConversion
// Author: James Chen
// Created: Saturday, May 15, 2010 1:04:09 PM
//
// Purpose: This stores all the conversions that are need
//
// Revisions: 
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////

/* Linear Conversions [5/15/2010 1:10 PM by: James Chen] */
#define MetrToFt 3.2808399
#define FtToMetr 0.3048

#define MiToMetr 1609.344
#define MetrToMi 0.000621371192

#define MiToYard 1760
#define YardToMi 0.000568181818

#define MetrToYard 1.0936133
#define YardToMetr 0.9144

#define InchToCM 2.54
#define CMToInch 0.393700787

#define MiToKM 1.6094
#define KMToMi 0.62137

#define AUToMi 92955887.6
#define MiToAU 0.000000107577922239

#define LightyearToMi 5878499810000


/* Weight Conversions [5/15/2010 1:10 PM by: James Chen] */
#define KgToLb 2.20462262
#define LbToKg 0.45359237

#define GramToLb 0.00220462262
#define LbToGram 453.59237

#define GrnToGram 0.06479891
#define GramToGrn 15.4323584

#define LbToGrn 7000
#define GrnToLb 0.000142857143

#define GrainToKg 0.00006479891
#define KgToGrain 15432.3584


/* Speed Conversions [5/15/2010 1:10 PM by: James Chen] */
#define SpeedOfLightMPH 670616629
#define SpeedOfLightMeterPerSec 299792458

#define KnotToMPH 1.15077945
#define MPHToKnot 0.868976242

#define MachToMPH 761.207051
#define MPHToMach 0.001313703018

#define MachToMeterPerSecond 340.29
#define MeterPerSecondToMach 0.002938669958

#define MachToFeetPerSecond 1116.43701
#define FeetPerSecondToMach 0.000895706601486


class CConversion
{
	////////////////////// Singleton Implementation Begins //////////////////////
private:

	CConversion(void);
	CConversion(const CConversion&);
	CConversion& operator =(const CConversion&);
	static CConversion *m_pInstance;

public:

	virtual ~CConversion(void);
	static CConversion *GetInstance(void);
	static void DeleteInstance(void);
	/////////////////////// Singleton Implementation Ends ///////////////////////

	double GoldenRatio(void)
	{
		return GOLDENRATIO;
	}

	/* Linear Conversions [5/15/2010 1:10 PM by: James Chen] */
	double FeetToMeter(double value, bool inverse = false);
	double YardToMeter(double value, bool inverse = false);
	double YardToMile(double value, bool inverse = false);
	double MeterToMile(double value, bool inverse = false);
	double KilometerToMile(double value, bool inverse = false);
	double CentimeterToInch(double value, bool inverse = false);

	/* Weight Conversions [5/15/2010 1:10 PM by: James Chen] */
	double PoundToKilogram(double value, bool inverse = false);
	double GramToPound(double value, bool inverse = false);
	double GrainToGram(double value, bool inverse = false);
	double PoundToGrain(double value, bool inverse = false);
	double GrainToKilogram(double value, bool inverse = false);

	/* Speed Conversions [5/15/2010 1:10 PM by: James Chen] */
	double FeetPerSecToMilePerHour(double value, bool inverse = false);
	double FeetPerSecToMach(double value, bool inverse = false);
	double MeterPerSecToMilePerHour(double value, bool inverse = false);
	double SpeedOfLightInMeterPerSec(bool inverse = false);
	double SpeedOfLightInMilePerHour(bool inverse = false);

};

/*---------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------*/